#include "abcyp.h"
#include <stdio.h>
#include <stdlib.h>
#include "literal.h"  //DEBBUG

/*PRE: Recibe un arbol Origen creado y no vacio y un puntero a otro arbol Destino creado y vacio.
  POS: Copia las ramas del arbol origen en el destino.*/
void copiar_ramas(TAB origen, TAB* destino){
  void* elem;
  int tamdato,error;

  tamdato=origen.tamdato;  //Viola abstraccion.
  elem=malloc(tamdato);

  if (AB_Vacio(*destino)){
    AB_ElemCte(origen,elem);
    AB_Insertar(destino,RAIZ,elem,&error);
  }

  AB_MoverCte(&origen,IZQ,&error);
  if (!error){
    AB_ElemCte(origen,elem);
    AB_Insertar(destino,IZQ,elem,&error);
    copiar_ramas(origen,destino);
    AB_MoverCte(&origen,PAD,&error);
    AB_MoverCte(destino,PAD,&error);
  }
  AB_MoverCte(&origen,DER,&error);
  if (!error){
    AB_ElemCte(origen,elem);
    AB_Insertar(destino,DER,elem,&error);
    copiar_ramas(origen,destino);
    AB_MoverCte(&origen,PAD,&error);
    AB_MoverCte(destino,PAD,&error);
  }
  free(elem);
}

/*PRE: Recibe un puntero a a un arbol.
  POS: Borra las subrramas desde la pocicion del corriente*/
void borrar_subarbol(TAB* arbol){
  int error;

  AB_MoverCte(arbol,IZQ,&error);
  if (!error){
    borrar_subarbol(arbol);
    AB_BorrarCte(arbol);
  }
  AB_MoverCte(arbol,DER,&error);
  if (!error){
    borrar_subarbol(arbol);
    AB_BorrarCte(arbol);
  }
}

/*PRE: Recibe 2 punteros a arboles y un tipo de movimiento.
       origen: es el puntero al arbol del cual se va a copiar los datos. Debe estar creado.
       destino: es el puntero al arbol en el cual se van a copiar los datos. no debe estar creado.
       movin: es el tipo de movimiento. Puede ser: RAIZ, DER o IZQ;
  POS: Copias las subrramas del origen desde el movimiento pedido en el arbol de salida*/
void AB_CopiarSubarbol( const TAB* origen, TAB* destino, int movim) {
  void* elem;
  int tamdato,error;
  TAB origen2=*origen;

  if (movim==PAD) return;  //Movimiento no admitido

  tamdato=origen2.tamdato;  //Viola abstraccion.
  elem=malloc(tamdato);

  AB_MoverCte(&origen2,movim,&error);
  if (error) return;
  AB_Crear(destino,tamdato); //Crea arbol destino

  copiar_ramas(origen2,destino);
  AB_MoverCte(destino,RAIZ,&error);
  free(elem);
}

/*PRE: Recibe 2 punteros a arboles y un tipo de movimiento.
       origen: es el puntero al arbol del cual se va a copiar los datos. Debe estar creado.
       destino: es el puntero al arbol en el cual se van a copiar los datos. Debe de estar creado.
       movin: es el tipo de movimiento. Puede ser: DER o IZQ;
  POS: Copias el arbol origen como una sub rama del destino en la pocicion declarada en movim respecto de su Corriente*/
void AB_PegarSubarbol( const TAB* origen, TAB* destino, int movim) {
  void* elem;
  int tamdato,error;
  TAB origen2=*origen;

  if ((movim==RAIZ)||(movim==PAD)) return;

  tamdato=origen2.tamdato;  //Viola abstraccion.
  elem=malloc(tamdato);

  AB_MoverCte(destino,movim,&error);
  if (!error){
    borrar_subarbol(destino);
    AB_BorrarCte(destino);
  }
  AB_MoverCte(&origen2,RAIZ,&error);
  if (error) return;
  AB_ElemCte(origen2,elem);
  AB_Insertar(destino,movim,elem,&error);
  free(elem);
  copiar_ramas(origen2,destino);
  //AB_MoverCte(destino,RAIZ,&error);
}

